home *** CD-ROM | disk | FTP | other *** search
/ Java Programmer's Toolkit / Java Programmer's Toolkit.iso / src / sun / tools / ttydebug / tty~1.jav
Encoding:
Text File  |  1996-01-12  |  39.7 KB  |  1,402 lines

  1. /*
  2.  * @(#)TTY.java    1.63 95/12/09
  3.  *
  4.  * Copyright (c) 1995 Sun Microsystems, Inc. All Rights Reserved.
  5.  *
  6.  * Permission to use, copy, modify, and distribute this software
  7.  * and its documentation for NON-COMMERCIAL purposes and without
  8.  * fee is hereby granted provided that this copyright notice
  9.  * appears in all copies. Please refer to the file "copyright.html"
  10.  * for further important copyright and licensing information.
  11.  *
  12.  * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF
  13.  * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
  14.  * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
  15.  * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR
  16.  * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
  17.  * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
  18.  */
  19.  
  20. package sun.tools.ttydebug;
  21. import sun.tools.debug.*;
  22. import java.util.*;
  23. import java.io.*;
  24. import java.net.*;
  25.  
  26. public class TTY implements DebuggerCallback {
  27.     RemoteDebugger debugger;
  28.     RemoteThread currentThread;
  29.     RemoteThreadGroup currentThreadGroup;
  30.     PrintStream out = null;
  31.     PrintStream console = null;
  32.  
  33.     private String lastArgs = null;
  34.     
  35.     private RemoteThread indexToThread(int index) throws Exception {
  36.     setDefaultThreadGroup();
  37.         RemoteThread list[] = currentThreadGroup.listThreads(true);
  38.     if (index == 0 || index > list.length) {
  39.         return null;
  40.     }
  41.     return list[index-1];
  42.     }
  43.  
  44.     private int parseThreadId(String idToken) throws Exception {
  45.     if (idToken.startsWith("t@")) {
  46.         idToken = idToken.substring(2);
  47.     }
  48.  
  49.     int threadId;
  50.     try {
  51.         threadId = Integer.valueOf(idToken).intValue();
  52.     } catch (NumberFormatException e) {
  53.         threadId = 0;
  54.     }
  55.     if (indexToThread(threadId) == null) {
  56.         out.println("\"" + idToken +
  57.                    "\" is not a valid thread id.");
  58.         return 0;
  59.     }
  60.     return threadId;
  61.     }
  62.  
  63.     private void printPrompt() throws Exception {
  64.         if (currentThread == null) {
  65.             out.print("> ");
  66.         } else {
  67.             out.print(currentThread.getName() + "[" +
  68.                       (currentThread.getCurrentFrameIndex() + 1)
  69.                       + "] ");
  70.         }
  71.         out.flush();
  72.     }
  73.  
  74.     public synchronized void printToConsole(String text) throws Exception {
  75.         console.print(text);
  76.         console.flush();
  77.     }
  78.  
  79.     public void breakpointEvent(RemoteThread t) throws Exception {
  80.     out.print("\nBreakpoint hit: ");
  81.  
  82.     RemoteStackFrame[] stack = t.dumpStack();
  83.     if (stack.length > 0) {
  84.         out.println(stack[0].toString());
  85.             currentThread = t;
  86.     } else {
  87.         out.println("Invalid thread specified in breakpoint.");
  88.     }
  89.         printPrompt();
  90.     }
  91.  
  92.     public void exceptionEvent(RemoteThread t, String errorText) 
  93.       throws Exception {
  94.     out.println("\n" + errorText);
  95.     t.setCurrentFrameIndex(0);
  96.     currentThread = t;
  97.         printPrompt();
  98.     }
  99.  
  100.     public void threadDeathEvent(RemoteThread t) throws Exception {
  101.     out.println("\n" + t.getName() + " died.");
  102.         if (t == currentThread) {
  103.             currentThread = null;
  104.         }
  105.         printPrompt();
  106.     }
  107.  
  108.     public void quitEvent() throws Exception {
  109.     out.println("\nThe application has exited");
  110.         System.exit(0);
  111.     }
  112.  
  113.     void classes() throws Exception {
  114.     RemoteClass list[] = debugger.listClasses();
  115.  
  116.     out.println("** classes list **");
  117.     for (int i = 0 ; i < list.length ; i++) {
  118.         out.println(list[i].description());
  119.     }
  120.     }
  121.  
  122.     void methods(StringTokenizer t) throws Exception {
  123.     if (!t.hasMoreTokens()) {
  124.         out.println("No class specified.");
  125.         return;
  126.     }
  127.  
  128.     String idClass = t.nextToken();
  129.     try {
  130.         RemoteClass cls = getClassFromToken(idClass);
  131.  
  132.         RemoteField methods[] = cls.getMethods();
  133.         for (int i = 0; i < methods.length; i++) {
  134.         out.println(methods[i].getType());
  135.         }
  136.     } catch (IllegalArgumentException e) {
  137.         out.println("\"" + idClass +
  138.                    "\" is not a valid id or class name.");
  139.     }
  140.     }
  141.  
  142.     int printThreadGroup(RemoteThreadGroup tg, int iThread) throws Exception {
  143.     out.println("Group " + tg.getName() + ":");
  144.     RemoteThread tlist[] = tg.listThreads(false);
  145.  
  146.     int maxId = 0;
  147.     int maxName = 0;
  148.     for (int i = 0 ; i < tlist.length ; i++) {
  149.         int len = tlist[i].description().length();
  150.         if (len > maxId)
  151.         maxId = len;
  152.         String name = tlist[i].getName();
  153.         int iDot = name.lastIndexOf('.');
  154.         if (iDot >= 0 && name.length() > iDot) {
  155.         name = name.substring(iDot + 1);
  156.         }
  157.         if (name.length() > maxName)
  158.         maxName = name.length();
  159.     }
  160.  
  161.     for (int i = 0 ; i < tlist.length ; i++) {
  162.         char buf[] = new char[80];
  163.         for (int j = 0; j < 79; j++) {
  164.         buf[j] = ' ';
  165.         }
  166.         buf[79] = '\0';
  167.         StringBuffer sbOut = new StringBuffer();
  168.         sbOut.append(buf);
  169.  
  170.         sbOut.insert(((i + iThread + 1) < 10) ? 1 : 0, (i + iThread + 1));
  171.         sbOut.insert(2, ".");
  172.         int iBuf = 4;
  173.         sbOut.insert(iBuf, tlist[i].description());
  174.         iBuf += maxId + 1;
  175.         String name = tlist[i].getName();
  176.         int iDot = name.lastIndexOf('.');
  177.         if (iDot >= 0 && name.length() > iDot) {
  178.         name = name.substring(iDot + 1);
  179.         }
  180.         sbOut.insert(iBuf, name);
  181.         iBuf += maxName + 1;
  182.         sbOut.insert(iBuf, tlist[i].getStatus());
  183.         sbOut.setLength(79);
  184.         out.println(sbOut.toString());
  185.     }
  186.  
  187.     RemoteThreadGroup tglist[] = debugger.listThreadGroups(tg);
  188.     for (int ig = 0; ig < tglist.length; ig++) {
  189.         if (tg != tglist[ig]) {
  190.         iThread += printThreadGroup(tglist[ig], iThread + tlist.length);
  191.         }
  192.     }
  193.     return tlist.length;
  194.     }
  195.  
  196.     private void setDefaultThreadGroup() throws Exception {
  197.     if (currentThreadGroup == null) {
  198.         RemoteThreadGroup tglist[] = debugger.listThreadGroups(null);
  199.         currentThreadGroup = tglist[0];    // system threadgroup
  200.     }
  201.     }
  202.     
  203.     void threads(StringTokenizer t) throws Exception {
  204.     if (!t.hasMoreTokens()) {
  205.         setDefaultThreadGroup();
  206.         printThreadGroup(currentThreadGroup, 0);
  207.         return;
  208.     }
  209.     String name = t.nextToken();
  210.     RemoteThreadGroup tglist[] = debugger.listThreadGroups(null);
  211.     for (int i = 0; i < tglist.length; i++) {
  212.         if (name.equals(tglist[i].getName())) {
  213.         printThreadGroup(tglist[i], 0);
  214.         return;
  215.         }
  216.     }
  217.     out.println(name + " is not a valid threadgroup name.");
  218.     }
  219.  
  220.     void threadGroups() throws Exception {
  221.     RemoteThreadGroup tglist[] = debugger.listThreadGroups(null);
  222.     for (int i = 0; i < tglist.length; i++) {
  223.         out.println(new Integer(i+1).toString() + ". " +
  224.                    tglist[i].description() + " " +
  225.                    tglist[i].getName());
  226.     }
  227.     }
  228.  
  229.     void setThread(int threadId) throws Exception {
  230.     setDefaultThreadGroup();
  231.     RemoteThread thread = indexToThread(threadId);
  232.     if (thread == null) {
  233.         out.println("\"" + threadId +
  234.                    "\" is not a valid thread id.");
  235.         return;
  236.     }
  237.     currentThread = thread;
  238.     }
  239.     
  240.     void thread(StringTokenizer t) throws Exception {
  241.     if (!t.hasMoreTokens()) {
  242.         out.println("Thread number not specified.");
  243.         return;
  244.     }
  245.     int threadId = parseThreadId(t.nextToken());
  246.     if (threadId == 0) {
  247.         return;
  248.     }
  249.     setThread(threadId);
  250.     }
  251.     
  252.     void threadGroup(StringTokenizer t) throws Exception {
  253.     if (!t.hasMoreTokens()) {
  254.         out.println("Threadgroup name not specified.");
  255.         return;
  256.     }
  257.     String name = t.nextToken();
  258.     RemoteThreadGroup tglist[] = debugger.listThreadGroups(null);
  259.     for (int i = 0; i < tglist.length; i++) {
  260.         if (name.equals(tglist[i].getName())) {
  261.         currentThreadGroup = tglist[i];
  262.         return;
  263.         }
  264.     }
  265.     out.println(name + " is not a valid threadgroup name.");
  266.     }
  267.     
  268.     void run(StringTokenizer t) throws Exception {
  269.     String argv[] = new String[100];
  270.     int argc = 0;
  271.  
  272.     if (!t.hasMoreTokens() && lastArgs != null) {
  273.         t = new StringTokenizer(lastArgs);
  274.         out.println("run " + lastArgs);
  275.     }
  276.     while (t.hasMoreTokens()) {
  277.         argv[argc++] = t.nextToken();
  278.             if (argc == 1) {
  279.                 // Expand name, if necessary.
  280.                 RemoteClass cls = debugger.findClass(argv[0]);
  281.                 if (cls == null) {
  282.                     out.println("Could not load the " + argv[0] + " class.");
  283.                     return;
  284.                 }
  285.                 argv[0] = cls.getName();
  286.             }
  287.     }
  288.  
  289.     if (argc > 0) {
  290.         RemoteThreadGroup newGroup = debugger.run(argc, argv);
  291.         if (newGroup != null) {
  292.         currentThreadGroup = newGroup;
  293.         setThread(1);
  294.         out.println("running ...");
  295.         } else {
  296.         out.println(argv[0] + " failed.");
  297.         }
  298.     } else {
  299.         out.println("No class name specified.");
  300.     }
  301.     }
  302.  
  303.     void load(StringTokenizer t) throws Exception {
  304.     if (!t.hasMoreTokens()) {
  305.         out.println("Class name not specified.");
  306.         return;
  307.     }
  308.     String idToken = t.nextToken();
  309.     RemoteClass cls = debugger.findClass(idToken);
  310.     if (cls == null) {
  311.         out.print(idToken + " not found");
  312.         out.println((idToken.indexOf('.') > 0) ?
  313.                    " (try the full name)" : "");
  314.     } else {
  315.         out.println(cls.toString());
  316.     }
  317.     }
  318.  
  319.     void suspend(StringTokenizer t) throws Exception {
  320.     if (!t.hasMoreTokens()) {
  321.         setDefaultThreadGroup();
  322.         RemoteThread list[] = currentThreadGroup.listThreads(true);
  323.         for (int i = 0; i < list.length; i++) {
  324.         list[i].suspend();
  325.         }
  326.         out.println("All (non-system) threads suspended.");
  327.     } else {
  328.         while (t.hasMoreTokens()) {
  329.         String idToken = t.nextToken();
  330.         int threadId;
  331.         try {
  332.             threadId = Integer.valueOf(idToken).intValue();
  333.         } catch (NumberFormatException e) {
  334.             threadId = 0;
  335.         }
  336.         RemoteThread thread = indexToThread(threadId);
  337.         if (thread == null) {
  338.             out.println("\"" + idToken +
  339.                        "\" is not a valid thread id.");
  340.             continue;
  341.         }
  342.         thread.suspend();
  343.         }
  344.     }
  345.     }
  346.  
  347.     void resume(StringTokenizer t) throws Exception {
  348.      if (!t.hasMoreTokens()) {
  349.         setDefaultThreadGroup();
  350.         RemoteThread list[] = currentThreadGroup.listThreads(true);
  351.         for (int i = 0; i < list.length; i++) {
  352.         list[i].resume();
  353.         }
  354.         if (currentThread != null) {
  355.         currentThread.resetCurrentFrameIndex();
  356.         }
  357.          out.println("All threads resumed.");
  358.      } else {
  359.          while (t.hasMoreTokens()) {
  360.          String idToken = t.nextToken();
  361.          int threadId;
  362.          try {
  363.              threadId = Integer.valueOf(idToken).intValue();
  364.          } catch (NumberFormatException e) {
  365.              threadId = 0;
  366.          }
  367.         RemoteThread thread = indexToThread(threadId);
  368.         if (thread == null) {
  369.              out.println("\"" + idToken +
  370.                        "\" is not a valid thread id.");
  371.              continue;
  372.          }
  373.          thread.resume();
  374.          if (thread == currentThread) {
  375.              currentThread.resetCurrentFrameIndex();
  376.          }
  377.           }
  378.     }
  379.     }
  380.  
  381.     void cont() throws Exception {
  382.     if (currentThread == null) {
  383.         out.println("Nothing suspended.");
  384.         return;
  385.     }
  386.     setDefaultThreadGroup();
  387.     RemoteThread list[] = currentThreadGroup.listThreads(true);
  388.     for (int i = 0; i < list.length; i++) {
  389.         list[i].cont();
  390.     }
  391.     currentThread.resetCurrentFrameIndex();
  392.     }
  393.  
  394.     void step() throws Exception {
  395.     if (currentThread == null) {
  396.         out.println("Nothing suspended.");
  397.         return;
  398.     }
  399.     try {
  400.         currentThread.step(true);
  401.     } catch (IllegalAccessError e) {
  402.         out.println("Current thread is not at breakpoint.");
  403.     }
  404.     }
  405.  
  406.     void next() throws Exception {
  407.     if (currentThread == null) {
  408.         out.println("Nothing suspended.");
  409.         return;
  410.     }
  411.     try {
  412.         currentThread.next();
  413.     } catch (IllegalAccessError e) {
  414.         out.println("Current thread is not at breakpoint.");
  415.     }
  416.     }
  417.  
  418.     void kill(StringTokenizer t) throws Exception {
  419.      if (!t.hasMoreTokens()) {
  420.         out.println("Usage: kill <threadgroup name> or <thread id>");
  421.         return;
  422.     }
  423.     while (t.hasMoreTokens()) {
  424.         String idToken = t.nextToken();
  425.         int threadId;
  426.         try {
  427.         threadId = Integer.valueOf(idToken).intValue();
  428.         } catch (NumberFormatException e) {
  429.         threadId = 0;
  430.         }
  431.         RemoteThread thread = indexToThread(threadId);
  432.         if (thread != null) {
  433.                 out.println("killing thread: " + thread.getName());
  434.         thread.stop();
  435.                 return;
  436.         } else {
  437.         /* Check for threadgroup name, skipping "system". */
  438.         RemoteThreadGroup tglist[] = debugger.listThreadGroups(null);
  439.         tglist = debugger.listThreadGroups(tglist[0]);
  440.         for (int i = 0; i < tglist.length; i++) {
  441.             if (tglist[i].getName().equals(idToken)) {
  442.                         out.println("killing threadgroup: " + idToken);
  443.             tglist[i].stop();
  444.             return;
  445.             }
  446.         }
  447.         
  448.         out.println("\"" + idToken +
  449.                    "\" is not a valid threadgroup or id.");
  450.         }
  451.     }
  452.     }
  453.  
  454.     void catchException(StringTokenizer t) throws Exception {
  455.      if (!t.hasMoreTokens()) {
  456.         String exceptionList[] = debugger.getExceptionCatchList();
  457.         for (int i = 0; i < exceptionList.length; i++) {
  458.         out.print("  " + exceptionList[i]);
  459.         if ((i & 4) == 3 || (i == exceptionList.length - 1)) {
  460.             out.println();
  461.         }
  462.         }
  463.     } else {
  464.         String idClass = t.nextToken();
  465.         try {
  466.         RemoteClass cls = getClassFromToken(idClass);
  467.         cls.catchExceptions();
  468.         } catch (Exception e) {
  469.         out.println("Invalid exception class name: " + idClass);
  470.         }
  471.     }
  472.     }
  473.     
  474.     void ignoreException(StringTokenizer t) throws Exception {
  475.      if (!t.hasMoreTokens()) {
  476.         String exceptionList[] = debugger.getExceptionCatchList();
  477.         for (int i = 0; i < exceptionList.length; i++) {
  478.         out.print("  " + exceptionList[i]);
  479.         if ((i & 4) == 3 || (i == exceptionList.length - 1)) {
  480.             out.println();
  481.         }
  482.         }
  483.     } else {
  484.         String idClass = t.nextToken();
  485.         try {
  486.         RemoteClass cls = getClassFromToken(idClass);
  487.         cls.ignoreExceptions();
  488.         } catch (Exception e) {
  489.         out.println("Invalid exception class name: " + idClass);
  490.         }
  491.     }
  492.     }
  493.     
  494.     void up(StringTokenizer t) throws Exception {
  495.     if (currentThread == null) {
  496.         out.println("Current thread not set.");
  497.         return;
  498.     }
  499.  
  500.     int nLevels = 1;
  501.     if (t.hasMoreTokens()) {
  502.         String idToken = t.nextToken();
  503.         int n;
  504.         try {
  505.         n = Integer.valueOf(idToken).intValue();
  506.         } catch (NumberFormatException e) {
  507.         n = 0;
  508.         }
  509.         if (n == 0) {
  510.         out.println("Usage: up [n frames]");
  511.         return;
  512.         }
  513.         nLevels = n;
  514.     }
  515.  
  516.     try {
  517.         currentThread.up(nLevels);
  518.     } catch (IllegalAccessError e) {
  519.         out.println("Thread isn't suspended.");
  520.     } catch (ArrayIndexOutOfBoundsException e) {
  521.         out.println("End of stack.");
  522.     }
  523.     }
  524.  
  525.     void down(StringTokenizer t) throws Exception {
  526.     if (currentThread == null) {
  527.         out.println("Current thread not set.");
  528.         return;
  529.     }
  530.  
  531.     int nLevels = 1;
  532.     if (t.hasMoreTokens()) {
  533.         String idToken = t.nextToken();
  534.         int n;
  535.         try {
  536.         n = Integer.valueOf(idToken).intValue();
  537.         } catch (NumberFormatException e) {
  538.         n = 0;
  539.         }
  540.         if (n == 0) {
  541.         out.println("usage: down [n frames]");
  542.         return;
  543.         }
  544.         nLevels = n;
  545.     }
  546.  
  547.     try {
  548.         currentThread.down(nLevels);
  549.     } catch (IllegalAccessError e) {
  550.         out.println("Thread isn't suspended.");
  551.     } catch (ArrayIndexOutOfBoundsException e) {
  552.         out.println("End of stack.");
  553.     }
  554.     }
  555.  
  556.     void dumpStack(RemoteThread thread) throws Exception {
  557.     RemoteStackFrame[] stack = thread.dumpStack();
  558.     if (stack.length == 0) {
  559.         out.println("Thread is not running (no stack).");
  560.     } else {
  561.         int nFrames = stack.length;
  562.         for (int i = thread.getCurrentFrameIndex(); i < nFrames; i++) {
  563.         out.print("  [" + (i + 1) + "] ");
  564.         out.println(stack[i].toString());
  565.         }
  566.     }
  567.     }
  568.  
  569.     void where(StringTokenizer t) throws Exception {
  570.     if (!t.hasMoreTokens()) {
  571.         if (currentThread == null) {
  572.         out.println("No thread specified.");
  573.         return;
  574.         }
  575.         dumpStack(currentThread);
  576.     } else {
  577.         String token = t.nextToken();
  578.         if (token.toLowerCase().equals("all")) {
  579.         setDefaultThreadGroup();
  580.         RemoteThread list[] = currentThreadGroup.listThreads(true);
  581.         for (int i = 0; i < list.length; i++) {
  582.             out.println(list[i].getName() + ": ");
  583.             dumpStack(list[i]);
  584.         }
  585.         } else {
  586.         int threadId = parseThreadId(token);
  587.         if (threadId == 0) {
  588.             return;
  589.         }
  590.         dumpStack(indexToThread(threadId));
  591.         }
  592.     }
  593.     }
  594.  
  595.     void trace(String cmd, StringTokenizer t) throws Exception {
  596.     if (!t.hasMoreTokens()) {
  597.         out.println("(i)trace < \"on\" | \"off\" >");
  598.         return;
  599.     }
  600.     
  601.     String v = t.nextToken();
  602.     boolean traceOn;
  603.     if (v.equals("on")) {
  604.         traceOn = true;
  605.     } else if (v.equals("off")) {
  606.         traceOn = false;
  607.     } else {
  608.         out.println("(i)trace < \"on\" | \"off\" >");
  609.         return;
  610.     }
  611.  
  612.     if (cmd.equals("trace")) {
  613.         debugger.trace(traceOn);
  614.     } else {
  615.         debugger.itrace(traceOn);
  616.     }
  617.     }
  618.  
  619.     void memory() throws Exception {
  620.     out.println("Free: " + debugger.freeMemory() + ", total: " +
  621.                debugger.totalMemory());
  622.     }
  623.  
  624.     void gc() throws Exception {
  625.         RemoteObject[] save_list = new RemoteObject[2];
  626.         save_list[0] = currentThread;
  627.         save_list[1] = currentThreadGroup;
  628.         debugger.gc(save_list);
  629.     }
  630.  
  631.     private RemoteClass getClassFromToken(String idToken) throws Exception {
  632.     RemoteObject obj;
  633.     if (idToken.startsWith("0x") ||
  634.         Character.isDigit(idToken.charAt(0))) {
  635.         /* It's an object id. */
  636.         int id;
  637.         try {
  638.         id = RemoteObject.fromHex(idToken);
  639.         } catch (NumberFormatException e) {
  640.         id = 0;
  641.         }
  642.         if (id == 0 || (obj = debugger.get(new Integer(id))) == null) {
  643.         throw new IllegalArgumentException();
  644.         } else if (!(obj instanceof RemoteClass)) {
  645.         throw new IllegalArgumentException();
  646.         }
  647.     } else {
  648.         /* It's a class */
  649.         obj = debugger.findClass(idToken);
  650.         if (obj == null) {
  651.         throw new IllegalArgumentException();
  652.         }
  653.     }
  654.     return (RemoteClass)obj;
  655.     }
  656.  
  657.     void listBreakpoints() throws Exception {
  658.         String bkptList[] = debugger.listBreakpoints();
  659.     if (bkptList.length > 0) {
  660.             out.println("Current breakpoints set:");
  661.             for(int i = 0; i < bkptList.length; i++) {
  662.                 out.println("\t" + bkptList[i]);
  663.             }
  664.     } else {
  665.         out.println("No breakpoints set.");
  666.     }
  667.     }
  668.  
  669.     void stop(StringTokenizer t) throws Exception {
  670.     if (!t.hasMoreTokens()) {
  671.         listBreakpoints();
  672.         return;
  673.     }
  674.     
  675.     String idClass = null;
  676.     try {
  677.         String modifier = t.nextToken();
  678.         boolean stopAt;
  679.         if (modifier.equals("at")) {
  680.         stopAt = true;
  681.         } else if (modifier.equals("in")) {
  682.         stopAt = false;
  683.         } else {
  684.         out.println("Usage: stop at <class>:<line_number> or");
  685.         out.println("       stop in <class>.<method_name>");
  686.         return;
  687.         }
  688.  
  689.         if (modifier.equals("at")) {
  690.         idClass = t.nextToken(": \t\n\r");
  691.         RemoteClass cls = getClassFromToken(idClass);
  692.  
  693.         String idLine = t.nextToken();
  694.         int lineno = Integer.valueOf(idLine).intValue();
  695.  
  696.         String err = cls.setBreakpointLine(lineno);
  697.         if (err.length() > 0) {
  698.             out.println(err);
  699.         } else {
  700.             out.println("Breakpoint set at " + cls.getName() +
  701.                        ":" + lineno);
  702.         }
  703.         } else {
  704.         idClass = t.nextToken(": \t\n\r");
  705.                 RemoteClass cls = null;
  706.                 String idMethod = null;
  707.  
  708.                 try {
  709.                     cls = getClassFromToken(idClass);
  710.                 } catch (IllegalArgumentException e) {
  711.                     // Try stripping method from class.method token.
  712.                     int idot = idClass.lastIndexOf(".");
  713.                     if (idot == -1) {
  714.                         out.println("\"" + idClass +
  715.                             "\" is not a valid id or class name.");
  716.                         return;
  717.                     }
  718.                     idMethod = idClass.substring(idot + 1);
  719.                     idClass = idClass.substring(0, idot);
  720.                     cls = getClassFromToken(idClass);
  721.                 }
  722.  
  723.                 if (idMethod == null) {
  724.                     idMethod = t.nextToken();
  725.                 }
  726.         RemoteField method = cls.getMethod(idMethod);
  727.         if (method == null) {
  728.             out.println("Class " + cls.getName() +
  729.                        " doesn't have a method " + idMethod);
  730.             return;
  731.         }
  732.         String err = cls.setBreakpointMethod(method);
  733.         if (err.length() > 0) {
  734.             out.println(err);
  735.         } else {
  736.             out.println("Breakpoint set in " + cls.getName() +
  737.                        "." + idMethod);
  738.         }
  739.         }
  740.     } catch (NoSuchElementException e) {
  741.         out.println("Usage: stop at <class>:<line_number> or");
  742.         out.println("       stop in <class>.<method_name>");
  743.     } catch (NumberFormatException e) {
  744.         out.println("Invalid line number.");
  745.     } catch (IllegalArgumentException e) {
  746.         out.println("\"" + idClass +
  747.                    "\" is not a valid id or class name.");
  748.     }
  749.     }
  750.  
  751.     void clear(StringTokenizer t) throws Exception {
  752.     if (!t.hasMoreTokens()) {
  753.         listBreakpoints();
  754.         return;
  755.     }
  756.     
  757.     String idClass = null;
  758.     String idMethod = null;
  759.     RemoteClass cls = null;
  760.     try {
  761.         idClass = t.nextToken(": \t\n\r");
  762.         try {
  763.             cls = getClassFromToken(idClass);
  764.             } catch (IllegalArgumentException e) {
  765.                 // Try stripping method from class.method token.
  766.                 int idot = idClass.lastIndexOf(".");
  767.                 if (idot == -1) {
  768.                     out.println("\"" + idClass +
  769.                         "\" is not a valid id or class name.");
  770.                     return;
  771.                 }
  772.                 idMethod = idClass.substring(idot + 1);
  773.                 idClass = idClass.substring(0, idot);
  774.                 cls = getClassFromToken(idClass);
  775.         RemoteField method = cls.getMethod(idMethod);
  776.         if (method == null) {
  777.             out.println("\"" + idMethod + 
  778.                 "\" is not a valid method name of class " +
  779.                 cls.getName());
  780.             return;
  781.         }
  782.         String err = cls.clearBreakpointMethod(method);
  783.             if (err.length() > 0) {
  784.             out.println(err);
  785.             } else {
  786.             out.println("Breakpoint cleared at " + 
  787.                 cls.getName() + "." + idMethod);
  788.         }
  789.         return;
  790.             }
  791.  
  792.         String idLine = t.nextToken();
  793.         int lineno = Integer.valueOf(idLine).intValue();
  794.  
  795.         String err = cls.clearBreakpointLine(lineno);
  796.         if (err.length() > 0) {
  797.         out.println(err);
  798.         } else {
  799.         out.println("Breakpoint cleared at " + cls.getName() +
  800.                    ": " + lineno);
  801.         }
  802.     } catch (NoSuchElementException e) {
  803.         out.println("Usage: clear <class>:<line_number>");
  804.         out.println("   or: clear <class>.<method>");
  805.     } catch (NumberFormatException e) {
  806.         out.println("Usage: clear <class>:<line_number>");
  807.         out.println("   or: clear <class>.<method>");
  808.     } catch (IllegalArgumentException e) {
  809.         out.println("\"" + idClass +
  810.                    "\" is not a valid id or class name.");
  811.     }
  812.     }
  813.  
  814.     void list(StringTokenizer t) throws Exception {
  815.     RemoteStackFrame frame = null;
  816.     if (currentThread == null) {
  817.         out.println("No thread specified.");
  818.         return;
  819.     }
  820.     try {
  821.         frame = currentThread.getCurrentFrame();
  822.     } catch (IllegalAccessError e) {
  823.         out.println("Current thread isn't suspended.");
  824.         return;
  825.     } catch (ArrayIndexOutOfBoundsException e) {
  826.         out.println("Thread is not running (no stack).");
  827.         return;
  828.     }
  829.     
  830.     int lineno;
  831.     if (t.hasMoreTokens()) {
  832.         String idLine = t.nextToken();
  833.         lineno = Integer.valueOf(idLine).intValue();
  834.     } else {
  835.         lineno = frame.getLineNumber();
  836.     }
  837.     int startLine = (lineno > 4) ? lineno - 4 : 1;
  838.     int endLine = startLine + 9;
  839.  
  840.     InputStream rawSourceFile = frame.getRemoteClass().getSourceFile();
  841.     if (rawSourceFile == null) {
  842.         out.println("Unable to find " + 
  843.                         frame.getRemoteClass().getSourceFileName());
  844.         return;
  845.     }
  846.  
  847.     DataInputStream sourceFile = new DataInputStream(rawSourceFile);
  848.     String sourceLine = null;
  849.  
  850.     /* Skip through file to desired window. */
  851.     for (int i = 1; i <= startLine; i++) {
  852.         sourceLine = sourceFile.readLine();
  853.     }
  854.     if (sourceLine == null) {
  855.         out.println(new Integer(lineno).toString() +
  856.                         " is an invalid line number for the file " +
  857.                         frame.getRemoteClass().getSourceFileName());
  858.     }
  859.  
  860.     /* Print lines */
  861.     for (int i = startLine; i < endLine && sourceLine != null; i++) {
  862.         out.print(new Integer(i).toString() + "\t" +
  863.                  ((i == lineno) ? "=> " : "   "));
  864.         out.println(sourceLine);
  865.         sourceLine = sourceFile.readLine();
  866.     }
  867.         
  868.     }
  869.  
  870.     /* Get or set the source file path list. */
  871.     void use(StringTokenizer t) throws Exception {
  872.     if (!t.hasMoreTokens()) {
  873.         out.println(debugger.getSourcePath());
  874.     } else {
  875.         debugger.setSourcePath(t.nextToken());
  876.     }
  877.     }
  878.  
  879.     /* Print all local variables in current stack frame. */
  880.     void locals() throws Exception {
  881.     if (currentThread == null) {
  882.         out.println("No default thread specified: " +
  883.                    "use the \"thread\" command first.");
  884.         return;
  885.     }
  886.     RemoteStackVariable rsv[] = currentThread.getStackVariables();
  887.     if (rsv == null || rsv.length == 0) {
  888.         out.println("No local variables: try compiling with -g");
  889.         return;
  890.     }
  891.     out.println("Local variables and arguments:");
  892.     for (int i = 0; i < rsv.length; i++) {
  893.         out.print("  " + rsv[i].getName());
  894.         if (rsv[i].inScope()) {
  895.         out.println(" = " + rsv[i].getValue().toString());
  896.         } else {
  897.         out.println(" is not in scope.");
  898.         }
  899.     }
  900.     return;
  901.     }
  902.  
  903.     /* Print a specified reference.  Returns success in resolving reference. */
  904.     boolean print(StringTokenizer t, boolean dumpObject, boolean recursing) throws Exception {
  905.     if (!t.hasMoreTokens()) {
  906.         out.println("No objects specified.");
  907.         return false;
  908.     }
  909.  
  910.     while (t.hasMoreTokens()) {
  911.         int id;
  912.         RemoteValue obj = null;
  913.  
  914.         String delimiters = ".[(";
  915.         String expr = t.nextToken();
  916.         StringTokenizer pieces =
  917.         new StringTokenizer(expr, delimiters, true);
  918.  
  919.         String idToken = pieces.nextToken(); // There will be at least one.
  920.         String varName = expr;
  921.         if (idToken.startsWith("t@")) {
  922.         /* It's a thread */
  923.         setDefaultThreadGroup();
  924.         RemoteThread tlist[] = currentThreadGroup.listThreads(true);
  925.         try {
  926.             id = Integer.valueOf(idToken.substring(2)).intValue();
  927.         } catch (NumberFormatException e) {
  928.             id = 0;
  929.         }
  930.         if (id <= 0 || id > tlist.length) {
  931.             out.println("\"" + idToken +
  932.                        "\" is not a valid thread id.");
  933.             return false;
  934.         }
  935.         obj = tlist[id - 1];
  936.  
  937.         } else if (idToken.startsWith("$s")) {
  938.         int slotnum;
  939.         try {
  940.             slotnum = Integer.valueOf(idToken.substring(2)).intValue();
  941.         } catch (NumberFormatException e) {
  942.             out.println("\"" + idToken +
  943.                        "\" is not a valid slot.");
  944.             return false;
  945.         }
  946.         if (currentThread != null) {
  947.             RemoteStackVariable rsv[] = currentThread.getStackVariables();
  948.             if (rsv == null || slotnum >= rsv.length) {
  949.             out.println("\"" + idToken +
  950.                        "\" is not a valid slot.");
  951.             return false;
  952.             }
  953.             obj = rsv[slotnum].getValue();
  954.         }
  955.         
  956.         } else if (idToken.startsWith("0x") ||
  957.                Character.isDigit(idToken.charAt(0))) {
  958.         /* It's an object id. */
  959.         try {
  960.             id = RemoteObject.fromHex(idToken);
  961.         } catch (NumberFormatException e) {
  962.             id = 0;
  963.         }
  964.         if (id == 0 || (obj = debugger.get(new Integer(id))) == null) {
  965.             out.println("\"" + idToken +
  966.                        "\" is not a valid id.");
  967.             return false;
  968.         }
  969.         } else {
  970.         /* See if it's a local stack variable */
  971.         if (currentThread != null) {
  972.             RemoteStackVariable rsv =
  973.             currentThread.getStackVariable(idToken);
  974.             if (rsv != null && !rsv.inScope()) {
  975.                 out.println(idToken + " is not in scope.");
  976.             return false;
  977.             }
  978.             obj = (rsv == null) ? null : rsv.getValue();
  979.         }
  980.         if (obj == null) {
  981.             if (idToken.equals("this") == false) {
  982.             /* See if it's an instance variable */
  983.             String instanceStr = "this." + idToken;
  984.             if (print(new StringTokenizer(instanceStr),
  985.                   dumpObject, true))
  986.                 return true;
  987.             }
  988.             
  989.             /* It's a class */
  990.             obj = debugger.findClass(idToken);
  991.             if (obj == null) {
  992.             if (!recursing) {
  993.                 out.println("\"" + expr + "\" is not a " +
  994.                            "valid id or class name.");
  995.             }
  996.             return false;
  997.             }
  998.         }
  999.         }
  1000.  
  1001.         RemoteInt noValue = new RemoteInt(-1);
  1002.         RemoteValue rv = noValue;
  1003.         String lastField = "";
  1004.         idToken = pieces.hasMoreTokens() ? pieces.nextToken() : null;
  1005.         while (idToken != null) {
  1006.  
  1007.         if (idToken.equals(".")) {
  1008.             if (pieces.hasMoreTokens() == false) {
  1009.             out.println("\"" + expr +
  1010.                        "\" is not a valid expression.");
  1011.             return false;
  1012.             }
  1013.             idToken = pieces.nextToken();
  1014.  
  1015.             if (rv != noValue) {
  1016.             /* attempt made to get a field on a non-object */
  1017.             out.println("\"" + lastField +
  1018.                        "\" is not an object.");
  1019.             return false;
  1020.             }
  1021.             lastField = idToken;
  1022.             
  1023.             rv = ((RemoteObject)obj).getFieldValue(idToken);
  1024.             if (rv == null) {
  1025.             out.println("\"" + idToken +
  1026.                        "\" is not a valid field of " +
  1027.                        obj.description());
  1028.             return false;
  1029.             }
  1030.             if (rv.isObject()) {
  1031.             obj = rv;
  1032.             rv = noValue;
  1033.             }
  1034.             idToken =
  1035.             pieces.hasMoreTokens() ? pieces.nextToken() : null;
  1036.  
  1037.         } else if (idToken.equals("[")) {
  1038.             if (pieces.hasMoreTokens() == false) {
  1039.             out.println("\"" + expr +
  1040.                        "\" is not a valid expression.");
  1041.             return false;
  1042.             }
  1043.             idToken = pieces.nextToken("]");
  1044.             try {
  1045.             int index = Integer.valueOf(idToken).intValue();
  1046.             rv = ((RemoteArray)rv).getElement(index);
  1047.             } catch (NumberFormatException e) {
  1048.             out.println("\"" + idToken +
  1049.                        "\" is not a valid decimal number.");
  1050.             return false;
  1051.             } catch (ArrayIndexOutOfBoundsException e) {
  1052.             out.println(idToken + " is out of bounds for " +
  1053.                        obj.description());
  1054.             return false;
  1055.             }
  1056.             if (rv != null && rv.isObject()) {
  1057.             obj = rv;
  1058.             rv = noValue;
  1059.             }
  1060.             if (pieces.hasMoreTokens() == false ||
  1061.             (idToken = pieces.nextToken()).equals("]") == false) {
  1062.             out.println("\"" + expr +
  1063.                        "\" is not a valid expression.");
  1064.             return false;
  1065.             }
  1066.             idToken = pieces.hasMoreTokens() ?
  1067.             pieces.nextToken(delimiters) : null;
  1068.  
  1069.         } else if (idToken.equals("(")) {
  1070.             out.println("print <method> not supported yet.");
  1071.             return false;
  1072.         } else {
  1073.             /* Should never get here. */
  1074.             out.println("invalid expression");
  1075.             return false;
  1076.         }
  1077.         }
  1078.  
  1079.         out.print(varName + " = ");
  1080.         if (rv != noValue) {
  1081.         out.println((rv == null) ? "null" : rv.description());
  1082.         } else if (dumpObject && obj instanceof RemoteObject) {
  1083.         out.println(obj.description() + " {");
  1084.  
  1085.         if (obj instanceof RemoteClass) {
  1086.             RemoteClass cls = (RemoteClass)obj;
  1087.  
  1088.             out.print("    superclass = ");
  1089.             RemoteClass superClass = cls.getSuperclass();
  1090.             out.println((superClass == null) ?
  1091.                        "null" : superClass.description());
  1092.  
  1093.             out.print("    loader = ");
  1094.             RemoteObject loader = cls.getClassLoader();
  1095.             out.println((loader == null) ?
  1096.                        "null" : loader.description());
  1097.  
  1098.             RemoteClass interfaces[] = cls.getInterfaces();
  1099.             if (interfaces != null && interfaces.length > 0) {
  1100.             out.println("    interfaces:");
  1101.             for (int i = 0; i < interfaces.length; i++) {
  1102.                 out.println("        " + interfaces[i]);
  1103.             }
  1104.             }
  1105.         }
  1106.  
  1107.         RemoteField fields[] = ((RemoteObject)obj).getFields();
  1108.         if (obj instanceof RemoteClass && fields.length > 0) {
  1109.             out.println();
  1110.         }
  1111.         for (int i = 0; i < fields.length; i++) {
  1112.             String name = fields[i].getType();
  1113.             String modifiers = fields[i].getModifiers();
  1114.             out.print("    " + modifiers + name + " = ");
  1115.             RemoteValue v = ((RemoteObject)obj).getFieldValue(i);
  1116.             out.println((v == null) ? "null" : v.description());
  1117.         }
  1118.         out.println("}");
  1119.         } else {
  1120.         out.println(obj.toString());
  1121.         }
  1122.     }
  1123.     return true;
  1124.     }
  1125.  
  1126.     void help
  1127.     () {
  1128.         out.println("** command list **");
  1129.         out.println("threads [threadgroup]     -- list threads");
  1130.         out.println("thread <thread id>        -- set default thread");
  1131.         out.println("suspend [thread id(s)]    -- suspend threads (default: all)");
  1132.         out.println("resume [thread id(s)]     -- resume threads (default: all)");
  1133.         out.println("where [thread id] | all   -- dump a thread's stack");
  1134.         out.println("threadgroups              -- list threadgroups");
  1135.         out.println("threadgroup <name>        -- set current threadgroup\n");
  1136.         out.println("print <id> [id(s)]        -- print object or field");
  1137.         out.println("dump <id> [id(s)]         -- print all object information\n");
  1138.         out.println("locals                    -- print all local variables in current stack frame\n");
  1139.         out.println("classes                   -- list currently known classes");
  1140.         out.println("methods <class id>        -- list a class's methods\n");
  1141.         out.println("stop in <class id>.<method> -- set a breakpoint in a method");
  1142.         out.println("stop at <class id>:<line> -- set a breakpoint at a line");
  1143.         out.println("up [n frames]             -- move up a thread's stack");
  1144.         out.println("down [n frames]           -- move down a thread's stack");
  1145.         out.println("clear <class id>:<line>   -- clear a breakpoint");
  1146.         out.println("step                      -- execute current line");
  1147.         out.println("cont                      -- continue execution from breakpoint\n");
  1148.         out.println("catch <class id>          -- break for the specified exception");
  1149.         out.println("ignore <class id>         -- ignore when the specified exception\n");
  1150.         out.println("list [line number]        -- print source code");
  1151.         out.println("use [source file path]    -- display or change the source path\n");
  1152.         out.println("memory                    -- report memory usage");
  1153.         out.println("gc                        -- free unused objects\n");
  1154.         out.println("load classname            -- load Java class to be debugged");
  1155.         out.println("run <class> [args]        -- start execution of a loaded Java class");
  1156. //        out.println("kill <thread(group)>      -- kill a thread or threadgroup\n");
  1157.         out.println("!!                        -- repeat last command");
  1158.         out.println("help (or ?)               -- list commands");
  1159.         out.println("exit (or quit)            -- exit debugger");
  1160.     }
  1161.  
  1162.     void executeCommand(StringTokenizer t) {
  1163.     String cmd = t.nextToken().toLowerCase();
  1164.  
  1165.     try {
  1166.         if (cmd.equals("print")) {
  1167.         print(t, false, false);
  1168.         } else if (cmd.equals("dump")) {
  1169.         print(t, true, false);
  1170.         } else if (cmd.equals("locals")) {
  1171.         locals();
  1172.         } else if (cmd.equals("classes")) {
  1173.         classes();
  1174.         } else if (cmd.equals("methods")) {
  1175.         methods(t);
  1176.         } else if (cmd.equals("threads")) {
  1177.         threads(t);
  1178.         } else if (cmd.equals("thread")) {
  1179.         thread(t);
  1180.         } else if (cmd.equals("suspend")) {
  1181.         suspend(t);
  1182.         } else if (cmd.equals("resume")) {
  1183.         resume(t);
  1184.         } else if (cmd.equals("threadgroups")) {
  1185.         threadGroups();
  1186.         } else if (cmd.equals("threadgroup")) {
  1187.         threadGroup(t);
  1188.         } else if (cmd.equals("catch")) {
  1189.         catchException(t);
  1190.         } else if (cmd.equals("ignore")) {
  1191.         ignoreException(t);
  1192.         } else if (cmd.equals("cont")) {
  1193.         cont();
  1194.         } else if (cmd.equals("step")) {
  1195.         step();
  1196.         } else if (cmd.equals("next")) {
  1197.         next();
  1198.             } else if (cmd.equals("kill")) {
  1199.                 kill(t);
  1200.         } else if (cmd.equals("where")) {
  1201.         where(t);
  1202.         } else if (cmd.equals("up")) {
  1203.         up(t);
  1204.         } else if (cmd.equals("down")) {
  1205.         down(t);
  1206.         } else if (cmd.equals("load")) {
  1207.         load(t);
  1208.         } else if (cmd.equals("run")) {
  1209.         run(t);
  1210.         } else if (cmd.equals("memory")) {
  1211.         memory();
  1212.             } else if (cmd.equals("gc")) {
  1213.                 gc();
  1214.         } else if (cmd.equals("trace") || cmd.equals("itrace")) {
  1215.         trace(cmd, t);
  1216.         } else if (cmd.equals("stop")) {
  1217.         stop(t);
  1218.         } else if (cmd.equals("clear")) {
  1219.         clear(t);
  1220.         } else if (cmd.equals("list")) {
  1221.         list(t);
  1222.         } else if (cmd.equals("use")) {
  1223.         use(t);
  1224.         } else if (cmd.equals("help") || cmd.equals("?")) {
  1225.         help();
  1226.         } else if (cmd.equals("quit") || cmd.equals("exit")) {
  1227.         debugger.close();
  1228.         System.exit(0);
  1229.         } else {
  1230.         out.println("huh? Try help...");
  1231.         }
  1232.     } catch (Exception e) {
  1233.         out.println("Internal exception:");
  1234.         out.flush();
  1235.         e.printStackTrace();
  1236.     }
  1237.     }
  1238.  
  1239.     void readCommandFile(File f) {
  1240.     try {
  1241.         if (f.canRead()) {
  1242.         // Process initial commands.
  1243.         DataInputStream inFile = 
  1244.             new DataInputStream(new FileInputStream(f));
  1245.         String ln;
  1246.         while ((ln = inFile.readLine()) != null) {
  1247.             StringTokenizer t = new StringTokenizer(ln);
  1248.             if (t.hasMoreTokens()) {
  1249.             executeCommand(t);
  1250.             }
  1251.         }
  1252.         }
  1253.     } catch (IOException e) {}
  1254.     }
  1255.  
  1256.     public TTY(String host, String password, String javaArgs, String args, 
  1257.                PrintStream outStream, PrintStream consoleStream,
  1258.                boolean verbose) throws Exception {
  1259.         System.out.println("Initializing jdb...");
  1260.     out = outStream;
  1261.     console = consoleStream;
  1262.         if (password == null) {
  1263.             debugger = new RemoteDebugger(javaArgs, this, verbose);
  1264.         } else {
  1265.             debugger = new RemoteDebugger(host, password, this, verbose);
  1266.         }
  1267.     DataInputStream in = new DataInputStream(System.in);
  1268.     String lastLine = null;
  1269.  
  1270.     if (args != null && args.length() > 0) {
  1271.         StringTokenizer t = new StringTokenizer(args);
  1272.         load(t);
  1273.         lastArgs = args;
  1274.     }
  1275.  
  1276.     Thread.currentThread().setPriority(Thread.NORM_PRIORITY);
  1277.  
  1278.     // Try reading user's startup file.
  1279.     File f = new File(System.getProperty("user.home") + 
  1280.         System.getProperty("file.separator") + "jdb.ini");
  1281.         if (!f.canRead()) {
  1282.             // Try opening $HOME/jdb.ini
  1283.             f = new File(System.getProperty("user.home") + 
  1284.                          System.getProperty("file.separator") + ".jdbrc");
  1285.         }
  1286.         readCommandFile(f);
  1287.  
  1288.     // Try opening local jdb.ini
  1289.     f = new File(System.getProperty("user.dir") + 
  1290.         System.getProperty("file.separator") + "startup.jdb");
  1291.         readCommandFile(f);
  1292.  
  1293.     // Process interactive commands.
  1294.     while (true) {
  1295.             printPrompt();
  1296.         String ln = in.readLine();
  1297.         if (ln == null) {
  1298.         out.println("Input stream closed.");
  1299.         return;
  1300.         }
  1301.  
  1302.         if (ln.startsWith("!!") && lastLine != null) {
  1303.         ln = lastLine + ln.substring(2);
  1304.         out.println(ln);
  1305.         }
  1306.  
  1307.         StringTokenizer t = new StringTokenizer(ln);
  1308.         if (t.hasMoreTokens()) {
  1309.         lastLine = ln;
  1310.         executeCommand(t);
  1311.         }
  1312.     }
  1313.     }
  1314.  
  1315.     public static void main(String argv[]) {
  1316.     // Get host attribute, if any.
  1317.     String localhost;
  1318.     try {
  1319.         localhost = InetAddress.getLocalHost().getHostName();
  1320.     } catch (Exception ex) {
  1321.         localhost = null;
  1322.     }    
  1323.     if (localhost == null) {
  1324.         localhost = "localhost";
  1325.     }
  1326.     String host = null;
  1327.     String password = null;
  1328.     String classArgs = "";
  1329.     String javaArgs = "";
  1330.         boolean verbose = false;
  1331.     
  1332.     for (int i = 0; i < argv.length; i++) {
  1333.         String token = argv[i];
  1334.         if (token.equals("-dbgtrace")) {
  1335.         verbose = true;
  1336.         } else if (token.equals("-cs") || token.equals("-checksource") ||
  1337.                token.equals("-noasyncgc") || token.equals("-prof") ||
  1338.                token.equals("-v") || token.equals("-verbose") ||
  1339.                token.equals("-verify") || token.equals("-noverify") ||
  1340.                token.equals("-verifyremote") ||
  1341.                token.equals("-verbosegc") ||
  1342.                token.startsWith("-ms") || token.startsWith("-mx") ||
  1343.                token.startsWith("-ss") || token.startsWith("-oss") ||
  1344.                token.startsWith("-D")) {
  1345.         javaArgs += token + " ";
  1346.         } else if (token.equals("-classpath")) {
  1347.         if (i == (argv.length - 1)) {
  1348.             System.out.println("No classpath specified.");
  1349.             System.exit(1);
  1350.         }
  1351.         javaArgs += token + " " + argv[++i] + " ";
  1352.         } else if (token.equals("-host")) {
  1353.         if (i == (argv.length - 1)) {
  1354.             System.out.println("No host specified.");
  1355.             System.exit(1);
  1356.         }
  1357.         host = argv[++i];
  1358.         } else if (token.equals("-password")) {
  1359.         if (i == (argv.length - 1)) {
  1360.             System.out.println("No password specified.");
  1361.             System.exit(1);
  1362.         }
  1363.         password = argv[++i];
  1364.         } else {
  1365.         classArgs += token + " ";
  1366.         }
  1367.     }
  1368.     if (host != null && password == null) {
  1369.         System.out.println("A debug password must be specified for " +
  1370.                    "remote debugging.");
  1371.         System.exit(1);
  1372.     }
  1373.     if (host == null) {
  1374.         host = localhost;
  1375.     }
  1376.  
  1377.     try {
  1378.         if (!host.equals(localhost) && password.length() == 0) {
  1379.         System.out.println(
  1380.             "No password supplied for accessing remote " +
  1381.             "Java interpreter.");
  1382.         System.out.println(
  1383.             "The password is reported by the remote interpreter" +
  1384.             "when it is started.");
  1385.                 System.exit(1);
  1386.             }
  1387.             new TTY(host, password, javaArgs, classArgs, 
  1388.                     System.out, System.out, verbose);
  1389.     } catch(SocketException se) {
  1390.         System.out.println("Failed accessing debugging session on " +
  1391.                    host + ": invalid password.");
  1392.     } catch(NumberFormatException ne) {
  1393.         System.out.println("Failed accessing debugging session on " +
  1394.                    host + ": invalid password.");
  1395.     } catch(Exception e) {        
  1396.         System.out.print("Internal exception:  ");
  1397.         System.out.flush();
  1398.         e.printStackTrace();
  1399.     }
  1400.     }
  1401. }
  1402.